package org.example.controller;

import com.alibaba.ttl.threadpool.TtlExecutors;
import jodd.util.concurrent.ThreadFactoryBuilder;
import org.example.threadlocal.UserContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/TransmittableThreadLocal")
public class TransmittableThreadLocalController {

    private static ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(10, new ThreadFactoryBuilder().setNameFormat("test-%d").get()));
    private static ExecutorService executorServiceInner = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(10, new ThreadFactoryBuilder().setNameFormat("test-%d").get()));

    @RequestMapping("/test")
    public String test() {
        // 获取用户信息
        String username = UserContext.getUser();
        //子线程使用快照获取父线程的用户信息，即使父线程已经修改了用户信息，不影响已提交的子线程的用户信息
        executorService.execute(() -> {
            String threadUsername = UserContext.getUser();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Thread1 username: " + threadUsername);
        });
        //父线程修改用户信息，子线程重新提交的快照将会收到影响
        UserContext.clear();
        executorService.execute(() -> {
            String threadUsername = UserContext.getUser();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Thread2 username: " + threadUsername);
        });

        System.out.println(username);
        return "Current user: " + username;
    }

    //测试嵌套的线程池 ttl是否还生效
    @RequestMapping("/test2")
    public String test2() {
        // 获取用户信息

        String username = UserContext.getUser();
        //子线程使用快照获取父线程的用户信息，即使父线程已经修改了用户信息，不影响已提交的子线程的用户信息
        executorService.execute(()->{
            executorServiceInner.execute(()->{
                String threadUsername = UserContext.getUser();
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("executorServiceInner username: " + threadUsername);
            });
        });
        System.out.println(username);
        return "Current user: " + username;
    }
}
